package com.aube.control.player;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.view.Surface;
import android.view.TextureView;

import com.aube.multiscreen.AbsPlayCallback;
import com.bokecc.sdk.mobile.play.DWMediaPlayer;
import com.huyn.baseframework.model.VideoPlayModel;
import com.huyn.baseframework.utils.Utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by huyn on 2015/9/23.
 * 主镜头的视频处理逻辑
 */
public class MajorTextureVideoHelper extends AbstractVideoHelper {

    private Timer timer = new Timer();
    private TimerTask timerTask;

    private AtomicBoolean mPaused = new AtomicBoolean(false);

    public MajorTextureVideoHelper(){}

    public MajorTextureVideoHelper(TextureView textureView, Context context, VideoPlayModel video, AbsPlayCallback playCallback) {
        this(textureView, context, video, playCallback, true);
    }

    public MajorTextureVideoHelper(TextureView textureView, Context context, VideoPlayModel video, AbsPlayCallback playCallback, boolean enableVolume) {
        this.enableVolume = enableVolume;
        this.mVideo = video;
        this.mContext = context;
        this.mTexture = textureView;
        setPlayCallback(playCallback);
        initParamOfFirstLanch();
        initPlayInfo(context, video);
    }

    private void initParamOfFirstLanch() {
        myListener = createMyListener();

        mTexture.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                Utils.Log(TAG, "major surface create!!!!!!!!!!");
                texturePrepared(new Surface(surface));
            }

            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
//                player.setSurface(new Surface(surface));
                Utils.Log(TAG, "major surface changed!!!!!!!!!!");
                if (isPrepared() && player != null) {
                    mLastPosition = player.getCurrentPosition();
                    Utils.Log(TAG, "major surface will record position:" + mLastPosition + " in onSurfaceTextureSizeChanged");
                }
            }

            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                Utils.Log(TAG, "major surface destroyed!!!!!!!!!!");
//                onDestroy();
                try {
                    if (isPrepared() && player != null) {
                        mLastPosition = player.getCurrentPosition();
                        Utils.Log(TAG, "major surface will record position:" + mLastPosition);
                    } else {
                        Utils.Log(TAG, "major surface fail to set record position");
                    }
                    if (!isDestroyed.get()) {
                        mRunningOnBackground.set(true);
                        pausePlay();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return true;
            }

            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
//                Utils.Log(TAG, "major surface updated!!!!!!!!!!");
            }
        });
    }

    protected MyMediaPlayerListener createMyListener() {
        return new MyMediaPlayerListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                if(!prepared.get())
                    return;
                if (iPlayCallback != null)
                    iPlayCallback.endPlay();
            }

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                if(iPlayCallback != null)
                    iPlayCallback.onError();
                return super.onError(mp, what, extra);
            }

            @Override
            public void onPrepared(MediaPlayer mp) {
                prepared.set(true);

                Utils.Log(getVideoId(), "prepare to play : " + player.getDuration());
                readyToPlay();
            }

            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                if(iPlayCallback != null)
                    iPlayCallback.updateBuffer(percent);
                mBufferdPercent = percent;
                Utils.Log(getVideoId(), "buffering : " + percent + "/" + getProgress()) ;
            }
        };
    }

    public void readyToPlay() {
        //modify on 2016.11.4 根据广告是否在播放,来设定player是否在onPrepare之后立刻播放
        if(mIsAdPlaying.get())
            return;

        if(!prepared.get())
            return;

        if(!mRunningOnBackground.get())
            play();
        mRunningOnBackground.set(false);

        if(mLastPosition > 0)
            seekTo(mLastPosition);

        if(player instanceof DWMediaPlayer) {
            Map<String, Integer> definitionMap = ((DWMediaPlayer) player).getDefinitions();
            if (definitionMap != null && iPlayCallback != null) {
                HashMap<Integer, String> definitions = new HashMap<>();
                Iterator<String> iterator = definitionMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String id = iterator.next();
                    definitions.put(definitionMap.get(id), id);
                }
                iPlayCallback.onReceiveDefinition(definitions, ((DWMediaPlayer) player).getDefinitionCode());
            }
        }
        Utils.Log(getVideoId(), "start to play") ;
    }

    private float getProgress() {
        return player.getCurrentPosition() * 100f/player.getDuration();
    }

    protected void texturePrepared(Surface surface) {
        Utils.Log(getVideoId(), "prepare surface...surface is null:" + (surface == null)) ;
        if(surface == null)
            return;
        try {
            if (mRunningOnBackground.get()) {
                mRunningOnBackground.set(false);
                //按home键暂停,会黑屏
                //player.prepareAsync();
                //player.start();
            }

            isDestroyed.set(false);

//            manageSound(enableVolume);

            if(player != null) {
                player.setSurface(surface);

                player.setAudioStreamType(AudioManager.STREAM_MUSIC);
                player.setScreenOnWhilePlaying(true);
                player.setOnBufferingUpdateListener(myListener);
                player.setOnPreparedListener(myListener);
                player.setOnCompletionListener(myListener);
                player.setOnSeekCompleteListener(myListener);
                player.setOnErrorListener(myListener);
            } else {
                textureForExoPrepared(surface);
            }
        } catch (Exception e) {
            Utils.Log("videoPlayer", e.getMessage());
            e.printStackTrace();
            if(iPlayCallback != null)
                iPlayCallback.onError();
        }
    }

    private void startTimer() {
        if(timer != null) {
            timer.cancel();
            timer = null;
        }
        timer = new Timer();
        // 通过定时器和Handler来更新进度
        timerTask = new TimerTask() {
            @Override
            public void run() {
                if (!isPrepared()) {
                    return;
                }
                mHandler.sendEmptyMessage(PLAY_WATCH);
            }
        };
        timer.schedule(timerTask, 0, 100);
    }

    @Override
    public void changeDefinition(String des, int definition) {
        if(isPrepared())
            mLastPosition = (int) getCurrentProgress();
        super.changeDefinition(des, definition);
    }

    public void onDestroy() {
        try {
            super.onDestroy();

            isDestroyed.set(true);

            //remove all listener
            iPlayCallback = null;

            if(timer != null)
                timer.cancel();
            timer = null;

            stopPlayer();
            releasePlayer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(msg.what==PLAY_WATCH) {
                if(player != null && player.isPlaying()) {
                    int currentPos = player.getCurrentPosition();
                    mLastPosition = currentPos;
                    int duration = player.getDuration();
                    if(iPlayCallback != null) {
                        iPlayCallback.updatePlay(currentPos, duration);

                        if(!iPlayCallback.hasFocused())
                            pausePlay();
                    }
                }

                if(exoPlayer != null && exoPlayer.getPlayWhenReady()) {
                    int currentPos = (int) exoPlayer.getCurrentPosition();
                    mLastPosition = currentPos;
                    int duration = (int) exoPlayer.getDuration();
                    mBufferdPercent = exoPlayer.getBufferedPercentage();
                    if(iPlayCallback != null) {
                        iPlayCallback.updatePlay(currentPos, duration);
                        iPlayCallback.updateBuffer((int) mBufferdPercent);
                        if(!iPlayCallback.hasFocused())
                            pausePlay();
                    }
                }
            }
        }
    };

    public boolean play() {
        if(prepared.get()) {
            if(player != null)
                player.start();

            mPaused.set(false);
            startTimer();

            if (iPlayCallback != null)
                iPlayCallback.startPlay();
        }
        return true;
    }

    public boolean startPlay() {
        Utils.Log(TAG, "start major player...");
        boolean startFromPause = false;
        if (player != null && !player.isPlaying()) {
            mPaused.set(false);
            player.start();
            mHandler.sendEmptyMessage(PLAY_WATCH);
            startFromPause = true;
        } else if(exoPlayer != null && !exoPlayer.getPlayWhenReady()) {
            mPaused.set(false);
            exoPlayer.setPlayWhenReady(true);
            mHandler.sendEmptyMessage(PLAY_WATCH);
            startFromPause = true;
        }

        startTimer();
        return startFromPause;
    }

    public void pausePlay() {
        Utils.Log(TAG, "pause player...");
        if (mPaused.get())
            return;
        if (iPlayCallback != null)
            iPlayCallback.clearLoading();
        mPaused.set(true);
        pausePlayer();

        /**暂停的时候也停止Handler的分发*/
        if(timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    @Override
    public int getCachedBuffer() {
        try {
            if(player != null) {
                int currentProgress = player.getCurrentPosition();
                int duration = player.getDuration();
//            if(mBufferdPercent == 100 && currentProgress < duration)
//                return ILLEGAL_BUFFER_RESULT;
                if (mBufferdPercent == 100 && currentProgress == 0)
                    return ILLEGAL_BUFFER_RESULT;

//            Utils.Log("BALANCE", getVideoId() + "+++" + currentProgress + "/" + duration + "..." + mBufferdPercent);

                int bufferProgress = (int) (mBufferdPercent * duration / 100);
                int result = (bufferProgress - currentProgress) / 1000;
                if (mBufferdPercent == 100 && result <= 0)
                    return PLAY_END;

                return result;
            } else {
                long currentProgress = getCurrentProgress();
                int mBufferdPercent = exoPlayer.getBufferedPercentage();
                long mBufferProgress = exoPlayer.getBufferPosition();
                if (mBufferdPercent == 100) {
                    if (currentProgress == 0)
                        return ILLEGAL_BUFFER_RESULT;
                    else
                        return BUFFER_COMPLETE;
                }

                int result = (int) ((mBufferProgress - currentProgress) / 1000);
                if (mBufferdPercent == 100 && result <= 0)
                    return PLAY_END;

                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ILLEGAL_BUFFER_RESULT;
    }

    public boolean isPaused() {
        return mPaused.get();
    }

    public void seekTo(int pos) {
        seekPlayer(pos);

        if(getDuration() > 0) {
            mBufferdPercent = pos * 100f / getDuration();
        } else {
            mBufferdPercent = 0;
        }
        Utils.Log(getVideoId(), "seek to : " + pos) ;
    }

}
